package com.gitee.melin.bee.core.jdbc.dialect.impl;

import com.gitee.melin.bee.core.jdbc.dialect.AbstractJdbcDialect;
import com.gitee.melin.bee.core.jdbc.enums.DataSourceType;
import com.gitee.melin.bee.core.jdbc.relational.BeeTableType;
import com.gitee.melin.bee.core.jdbc.relational.ConnectionInfo;
import java.sql.*;
import org.apache.commons.lang3.StringUtils;

/** https://github.com/IBM/trino-db2 */
public class KingbaseESJdbcDialect extends AbstractJdbcDialect {

    @Override
    public DataSourceType getDataSourceType() {
        return DataSourceType.KINGBASEES;
    }

    public KingbaseESJdbcDialect(ConnectionInfo connectionInfo) {
        super(connectionInfo);
    }

    public KingbaseESJdbcDialect(Connection connection) {
        super(connection);
    }

    @Override
    protected boolean filterSchema(String schemaName) {
        if (schemaName.startsWith("sys_")) {
            return false;
        }
        return super.filterSchema(schemaName);
    }

    @Override
    protected Driver getDriver() {
        return loadDriver(DataSourceType.KINGBASEES.getDriverClass());
    }

    @Override
    protected String getSelectTablesSql(String tableName) {
        String sql = "SELECT n.nspname              AS TABLE_SCHEMA\n"
                + "     , c.relname              AS TABLE_NAME\n"
                + "     , c.relkind as TABLE_TYPE\n"
                + "     , obj_description(c.oid) AS TABLE_COMMENT\n"
                + "     , c.reltuples AS TABLE_ROWS\n"
                + "     , cast(c.relpages as bigint) * 8 * 1024 as DATA_SIZE\n"
                + "     , (CASE WHEN c.relkind = 'p' THEN 'p' ELSE null END) as TABLE_PARTITION\n"
                + "     , null AS CREATE_TIME\n"
                + "     , null AS UPDATE_TIME\n"
                + "FROM pg_class c\n"
                + "         LEFT JOIN pg_namespace n\n"
                + "                   ON n.oid = c.relnamespace\n"
                + "WHERE c.relkind in ('r', 'f', 'p', 'v', 'm')\n"
                + "  AND (c.relpartbound is null or c.relpartbound ='')\n"
                + "  AND n.nspname = :schemaName";

        if (StringUtils.isNotBlank(tableName)) {
            sql += " AND c.relnam = :tableName";
        }
        return sql;
    }

    @Override
    protected BeeTableType getTableType(String type) {
        if (StringUtils.equalsIgnoreCase(type, "v")) {
            return BeeTableType.VIEW;
        } else if (StringUtils.equalsIgnoreCase(type, "r")) {
            return BeeTableType.TABLE;
        } else if (StringUtils.equalsIgnoreCase(type, "m")) {
            return BeeTableType.MATERIALIZED_VIEW;
        } else {
            throw new IllegalArgumentException("table type is invalid: " + type);
        }
    }

    @Override
    protected String createTableSql(BeeTableType type, String schemaName, String tableName) {
        if (BeeTableType.TABLE == type) {
            return "SELECT DBMS_METADATA.GET_DDL('TABLE', '"
                    + tableName
                    + "', '"
                    + schemaName
                    + "') as ct_script FROM DUAL";
        } else if (BeeTableType.VIEW == type) {
            return "SELECT DBMS_METADATA.GET_DDL('TABLE', '"
                    + tableName
                    + "', '"
                    + schemaName
                    + "') as ct_script FROM DUAL";
        } else {
            throw new RuntimeException("not support: " + type);
        }
    }

    @Override
    protected String getDDLColumnName(BeeTableType type) {
        return "ct_script";
    }
}
